﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using Citi.Scheduler.Domain;
using Citi.Helpers;
using System.Threading;
using Citi.Scheduler.Domain.Utils;

namespace Citi.Scheduler.ConsoleUi.RestartServices
{
    public class Program
    {
        private const int TimeoutMilliseconds = 30000;
        private static List<int> MachineAlreadyRestarted { get; set; }
        private static string NetworkUser { get { return ConfigurationManager.AppSettings["NetworkUser"]; } }
        private static string NetWorkPassword { get { return ConfigurationManager.AppSettings["NetWorkPassword"]; } }

        static void Main(string[] args)
        {
            var asdas = "";
            var asdsdsd = asdas;
            //var classType = new Domain.Application().GetType().GetProperty("Thread.CurrentThread.CurrentCulture");
            //var asdas =  new Domain.Application().GetType().GetProperties();

            //using (var client = new SchedulerWcf.())
            //{
            //    var parameters = new Dictionary<string, string>
            //    {
            //        {"ReportFolder", @"\\lacbra001fs0009\Data_Grp1\FPCRelat\PTS Report teste"},
            //        {"ReportExtension", ".xlsx"},
            //        {"ReportPattern", @"BookOfWorkLAG2014"},
            //        {"FriendlyReportName", @"PTS LAG Report - Current Year - Teste"},
            //        {"EmailAddressUsers", "nd61955"},
            //        {"EmailAddressError", "nd61955"}
            //    };

            //    client.ExecuteRoutineOnDemandById(89, parameters);
            //}

            //return;
            MachineAlreadyRestarted = new List<int>();
            var util = new Util();

            try
            {
                while (true)
                {
                    Console.WriteLine("{0} Reading Machines", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"));
                    var machines = new Machine().SelectAllActive<Machine>();//.Where(x=> x.ExecutionCenter || x.MonitorCenter || x.SchedulerCenter);

                    foreach (var machine in machines.Where(x => !MachineAlreadyRestarted.Contains(x.Id)))
                    {
                        Console.WriteLine("{0} Machine: {1}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), machine.HostName);

                        //var routinesInProgress = machine.RoutineExecutions.Where(x => x.InProgress
                        //        && x.LastHistory.Date > DateTime.Now.AddMinutes(-(x.Routine.EstimatedTime + x.Routine.EstimatedTime * x.Routine.PercentageAcceptableVariation / 100)));

                        //if (machine.RoutineInProgress == null)
                        if (!util.MachineIsRunning(machine.Id))
                        {
                            var hostname = machine.FullName.Contains("lac") ? machine.HostName : machine.FullName;

                            StopService(hostname, machine.SchedulerCenter, Machine.ServiceSchedulerName);
                            StopService(hostname, machine.MonitorCenter, Machine.ServiceMonitorName);
                            StopService(hostname, machine.ExecutionCenter, Machine.ServiceExecutionName);

                            Thread.Sleep(5000);

                            StartService(hostname, machine.ExecutionCenter, Machine.ServiceExecutionName);
                            StartService(hostname, machine.SchedulerCenter, Machine.ServiceSchedulerName);
                            StartService(hostname, machine.MonitorCenter, Machine.ServiceMonitorName);

                            MachineAlreadyRestarted.Add(machine.Id);
                        }
                        else
                            Console.WriteLine("{0} Is running a routine at this moment", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"));

                        Console.WriteLine();
                    }

                    if (MachineAlreadyRestarted.Count() == machines.Count())
                    {
                        const int sleepTime = 7200000;
                        Console.WriteLine("{0} Execution will sleep for {1} hours.", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), sleepTime / 3600000);
                        MachineAlreadyRestarted = new List<int>();
                        //DeleteDuplicates();
                        Thread.Sleep(sleepTime);
                    }
                    else
                    {
                        const int sleepTime = 300000;
                        Console.WriteLine("{0} Execution will sleep for {1} minutes.", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), sleepTime / 60000);
                        //DeleteDuplicates();
                        Thread.Sleep(sleepTime);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), e.Message);
                //DeleteDuplicates();
                Thread.Sleep(600000);
            }
        }

        private static void DeleteDuplicates()
        {
            Context.Instance.Machines.MergeOption = System.Data.Objects.MergeOption.OverwriteChanges;
            var machines = new GeneralAction().SelectAllActive<Machine>().Where(x => x.Id > 96);

            foreach (var machine in machines)
            {
                machine.Delete(machine);
            }
        }

        private static void StopService(string machine, bool center, string serviceName)
        {
            try
            {
                WindowsUtil.StopService(serviceName, machine, TimeoutMilliseconds);

                Console.WriteLine("{0} {1} {2}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), serviceName, "stopped");
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), e.Message);
                var i = 0;

                while (i < 4)
                {
                    try
                    {
                        WindowsUtil.StopService(serviceName, machine, TimeoutMilliseconds);

                        Console.WriteLine("{0} {1} {2}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), serviceName, "stopped");
                    }
                    catch (Exception e1)
                    {
                        Console.WriteLine("{0} {1}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), e1.Message);
                    }

                    i++;
                }
            }
        }

        private static void StartService(string machine, bool center, string serviceName)
        {
            try
            {
                if (!center) return;

                WindowsUtil.StartService(serviceName, machine, TimeoutMilliseconds);

                Console.WriteLine("{0} {1} {2}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), serviceName, center ? "started" : "stopped");
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} {1}", DateTime.Now.ToString("dd/MM/yyy HH:mm:ss"), e.Message);
            }
        }
    }

    public class Util
    {
        public bool MachineIsRunning(int machineId)
        {
            using (var client = new SchedulerMonitorWcf.MonitorClient())
                return client.IsMachineRunningRoutine(machineId);
        }
    }
}
